﻿#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <string.h>

#include "log.h"

const char* logLevelNames[] = {
    "LOG_DEBUG",
    "LOG_INFO",
    "LOG_WARNING",
    "LOG_ERROR",
    "LOG_NONE"
};

LogLevel current_log_level = LOG_LEVEL; // 这里是变量定义  

// 互斥锁
pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;

// 获取当前时间字符串，精确到毫秒
char* get_current_time_string() {
    struct timeval tv;
    struct tm timeinfo;
    char* buffer = malloc(30 * sizeof(char));  // 分配足够的空间存储时间字符串

    if (buffer == NULL) {
        perror("Memory allocation failed");
        return NULL;
    }

    gettimeofday(&tv, NULL);
    //localtime(&tv.tv_sec);
    localtime_r(&tv.tv_sec, &timeinfo);  // 使用线程安全的 localtime_r
    strftime(buffer, 20, "%Y-%m-%d %H:%M:%S", &timeinfo);  // 生成时间字符串，精确到秒
    snprintf(buffer + 19, 11, ".%03ld", (long)tv.tv_usec / 1000);  // 添加毫秒部分

    return buffer;
}

// 设置日志级别
void set_log_level(LogLevel level) {
    current_log_level = level;
}

// 日志打印函数，支持格式化字符串和简单字符串
void log_message(LogLevel level, const char* format, va_list args) {
    if (level >= current_log_level) {
        char* time_str = get_current_time_string();
        const char* level_str;

        switch (level) {
        case LOG_DEBUG:
            level_str = "DEBUG";
            break;
        case LOG_INFO:
            level_str = "INFO";
            break;
        case LOG_WARNING:
            level_str = "WARNING";
            break;
        case LOG_ERROR:
            level_str = "ERROR";
            break;
        default:
            level_str = "UNKNOWN";
            break;
        }

        // 用于存储格式化后的消息
        char message[1024];

        // 使用传入的 va_list 参数格式化消息
        vsnprintf(message, sizeof(message), format, args);

        // 确保线程安全
        pthread_mutex_lock(&log_mutex);
        printf("[%s] [%s] %s\n", time_str, level_str, message);
        pthread_mutex_unlock(&log_mutex);

        free(time_str);  // 释放分配的内存
    }
}

// 便捷的日志打印函数
void log_info(const char* format, ...) {
    LogLevel level = LOG_INFO;
    va_list args;
    va_start(args, format);
    log_message(level, format, args);
    va_end(args);
}

void log_debug(const char* format, ...) {
    LogLevel level = LOG_DEBUG;
    va_list args;
    va_start(args, format);
    log_message(level, format, args);
    va_end(args);
}

void log_warning(const char* format, ...) {
    LogLevel level = LOG_WARNING;
    va_list args;
    va_start(args, format);
    log_message(level, format, args);
    va_end(args);
}

void log_error(const char* format, ...) {
    LogLevel level = LOG_ERROR;
    va_list args;
    va_start(args, format);
    log_message(level, format, args);
    va_end(args);
}

void log_debug_print(unsigned char* buffer, size_t size) {
    
    if (current_log_level == LOG_DEBUG) {
        log_debug("Raw Data:");
        pthread_mutex_lock(&log_mutex); // 加锁  
        for (size_t i = 0; i < size; i += 16) {
            // 打印地址  
            printf("%04zx   ", i);

            // 打印十六进制数据  
            for (size_t j = 0; j < 16; ++j) {
                if (i + j < size) {
                    printf("%02x ", buffer[i + j]);
                }
                else {
                    printf("   ");  // 填充空格以保持格式  
                }
            }

            printf("   "); // 分隔十六进制和 ASCII 部分  

            // 打印对应的 ASCII 字符  
            for (size_t j = 0; j < 16; ++j) {
                if (i + j < size) {
                    unsigned char c = buffer[i + j];
                    // 控制非可打印字符  
                    printf("%c", (c >= 32 && c <= 126) ? c : '.'); // 控制输出  
                }
                else {
                    printf(" "); // 为空的字符位置  
                }
            }
            printf("\n");
        }
        printf("\n");
        pthread_mutex_unlock(&log_mutex); // 解锁  
        
    }
    
}
void log_print_level() {
    pthread_mutex_lock(&log_mutex);
    char* time_str = get_current_time_string();
    printf("[%s] 当前日志等级：%s\n", time_str, logLevelNames[current_log_level]);
    pthread_mutex_unlock(&log_mutex);
}
